<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="user-scalable=no">
    <title>重心法选址</title>
    <meta charset="utf-8">
    <meta name="viewport" content="user-scalable=no">
    <style>
       canvas{border: 3px solid red;} 
      
       button{
             background: #2f435e;
             color:#f2f2f2;
             padding : 10px;
             font-size : 16px;
             border-radius: 40px;
             transition:all linear 0.30s;
             width:100px;
             height: 50px;
        }
        button:disabled{
            background-color: gray;
            padding : 10px;
             font-size : 16px;
             border-radius: 40px;
             transition:all linear 0.30s;
             width:100px;
             height: 50px;
        }
        
    </style>
</head>
<body>
<canvas id="map" width="680" height="300" style="border:solid"> </canvas>
<div style="margin-left:160px">
    <button id = "select" onclick = "listen();">选择需求</button>
    
    <button id = "cal" onclick = "start();">计算</button>
    
    <button id = "restart" onclick = "location.reload();">重新开始</button>
    </div>
    <div id = "info" style = "color:black; margin-top: 30px;"><li style="color:red;">注意，便于显示，坐标进行了取整处理,已知道bug有坐标小于(0,0)时会放弃继续运算</li></div>
<script>
function $(name){
    cell = document.getElementById(name);
    return cell;
}

a = [];
b = [];
c = [];
d = [];
asum = 0;
bsum = 0;

function listen(){
    $("select").disabled =true;
    if($("cal").disabled==false){
        $("map").addEventListener("mousedown",getPoint,false);
    }
}


function getPoint(e){
    var x = e.pageX;
    var y = e.pageY;
    num = prompt("输入需求量");
    if (!isNaN(num)&&num){
        c.push(num);
    }else{
        alert("重新输入");
        location.reload(); 
    }
    a.push(x);
    b.push(y);
    draw(x,y);
    info.innerHTML =info.innerHTML+  "<li>需求点的坐标："+x+"  ,  "+y+"  "+"需求量为"+num+"</li>";

}

tc =[];
//O(m*n^2)
function start(){

    $("cal").disabled =true;
    $("map").removeEventListener("mousedown",getPoint,false);
    
    
    //计算各点重心和，获取初始点
    if(a.length>=2){
        for(var i = 0; i<a.length;i++){
            asum += a[i];
            bsum += b[i];
        }
        af = asum/a.length>>0;
        bf = bsum/b.length>>0;

        //console.log(af);
        
        ctx.fillStyle ="#CCFF99";
        draw(af,bf);

        
        //console.log(a);
        //console.log(b);
        //计算第一次距离和成本
        for(var i = 0; i<a.length;i++){
          d.push(distance(af,bf,a[i],b[i]))
        }

        //console.log(d);
        tc.push(totalCost(d,c));

        info.innerHTML =info.innerHTML+ "<li>初始计算得到的x1，y1"+":  "+af+"  ,  "+bf+"        成本为"+tc[0]+"</li>" ;
        
        var temp =1;
        tc[temp] = tc[0]-0.01;
        //迭代计算
        while(tc[temp]<tc[temp-1]){
            
            af = nextpoint(a,c,d)>>0;
            bf = nextpoint(b,c,d)>>0;
            //console.log(d);
            d.splice(0);
            for(var i = 0; i<a.length;i++){
                d.push(distance(af,bf,a[i],b[i]));
            }
            
            tc.push(totalCost(d,c));

            if(tc[temp]<tc[temp+1]){
                break;
            }

            draw(af,bf);   
            info.innerHTML =info.innerHTML+ "<li>第"+temp+"次迭代得到的x*，y*"+":  "+af+"  ,  "+bf+"        成本为"+tc[temp+1]+"</li>" ;
            temp ++; 
            //console.log(temp);
        }
        ctx.fillStyle ="#CC3333";
        draw(af,bf);
        //console.log(c);

    }else{
        alert("不能少于两个需求点");
    }
}

function init(){
    ctx = $("map").getContext("2d");  
    info = $("info");
    var img = new Image();
    img.src = "map.jpg";
    img.onload = function(){
        ctx.drawImage(img,0,0,680,300);
    }
    ctx.fillStyle = "#FF6666";
}

function nextpoint(x,w,d){
    var res1 = 0;
    var res2 = 0;
    for(var i = 0; i<a.length;i++){
        res1 += w[i]*x[i]/d[i];
        res2 += w[i]/d[i];       
    }
    return res1/res2>>0;
}



function totalCost(d,c){
    var tf=0;
    for(var i = 0; i<a.length;i++){
           tf+=d[i]*c[i];
        }
    return tf;
}
function distance(x1,y1,x2,y2){
    dist = Math.sqrt((x1-x2)**2+(y1-y2)**2);
    //console.log((x1-x2)**2+(y1-y2)**2);
    return dist>>0;
}

function draw(x,y){
    ctx.beginPath();
    ctx.arc(x,y,10,0,360,false);
    ctx.fill();
    ctx.closePath();
}


window.onload = init();

</script>
</article>
</body>
</html>